﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace ru.yourpictures.Core.Imaging.Filters
{
    [FilterImplementation(GdiPlusImplemented = true, LowLevelImplemented = false)]
    public class Resize : FilterBase
    {
        private int _newWidth = 0;
        private int _newHeight = 0;
        private bool _useBilinear = true;

        #region Public properties
        public bool UseBilinear
        {
            get { return _useBilinear; }
            set { _useBilinear = value; }
        }

        public int NewHeight
        {
            get { return _newHeight; }
            set { _newHeight = value; }
        }

        public int NewWidth
        {
            get { return _newWidth; }
            set { _newWidth = value; }
        }
        #endregion

        #region Low level resizing
        /*
        public bool Apply(Bitmap b)
        {
            Bitmap bTemp = (Bitmap)b.Clone();
            b = new Bitmap(_width, _height, bTemp.PixelFormat);

            double nXFactor = (double)bTemp.Width / (double)_width;
            double nYFactor = (double)bTemp.Height / (double)_height;

            if (_useBilinear)
            {
                double fraction_x, fraction_y, one_minus_x, one_minus_y;
                int ceil_x, ceil_y, floor_x, floor_y;
                System.Drawing.Color c1 = new System.Drawing.Color();
                System.Drawing.Color c2 = new System.Drawing.Color();
                System.Drawing.Color c3 = new System.Drawing.Color();
                System.Drawing.Color c4 = new System.Drawing.Color();
                byte red, green, blue;

                byte b1, b2;

                for (int x = 0; x < b.Width; ++x)
                    for (int y = 0; y < b.Height; ++y)
                    {
                        // Setup

                        floor_x = (int)Math.Floor(x * nXFactor);
                        floor_y = (int)Math.Floor(y * nYFactor);
                        ceil_x = floor_x + 1;
                        if (ceil_x >= bTemp.Width) ceil_x = floor_x;
                        ceil_y = floor_y + 1;
                        if (ceil_y >= bTemp.Height) ceil_y = floor_y;
                        fraction_x = x * nXFactor - floor_x;
                        fraction_y = y * nYFactor - floor_y;
                        one_minus_x = 1.0 - fraction_x;
                        one_minus_y = 1.0 - fraction_y;

                        c1 = bTemp.GetPixel(floor_x, floor_y);
                        c2 = bTemp.GetPixel(ceil_x, floor_y);
                        c3 = bTemp.GetPixel(floor_x, ceil_y);
                        c4 = bTemp.GetPixel(ceil_x, ceil_y);

                        // Blue
                        b1 = (byte)(one_minus_x * c1.B + fraction_x * c2.B);

                        b2 = (byte)(one_minus_x * c3.B + fraction_x * c4.B);

                        blue = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

                        // Green
                        b1 = (byte)(one_minus_x * c1.G + fraction_x * c2.G);

                        b2 = (byte)(one_minus_x * c3.G + fraction_x * c4.G);

                        green = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

                        // Red
                        b1 = (byte)(one_minus_x * c1.R + fraction_x * c2.R);

                        b2 = (byte)(one_minus_x * c3.R + fraction_x * c4.R);

                        red = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

                        b.SetPixel(x, y, System.Drawing.Color.FromArgb(255, red, green, blue));
                    }
            }
            else
            {
                for (int x = 0; x < b.Width; ++x)
                    for (int y = 0; y < b.Height; ++y)
                        b.SetPixel(x, y, bTemp.GetPixel((int)(Math.Floor(x * nXFactor)), (int)(Math.Floor(y * nYFactor))));
            }

            return true;
        }
         * */
        #endregion

        protected override void FilterImplementation()
        {
            throw new NotImplementedException("Low level mode is not implemented");
        }

        public override void Apply(Bitmap b)
        {
            b = new Bitmap(b, _newWidth, _newHeight);
        }

        public override Bitmap Convert(Bitmap b)
        {
            return new Bitmap(b, _newWidth, _newHeight);
        }

        /// <summary>
        /// Suppose proportional resizing
        /// </summary>
        /// <param name="img"></param>
        /// <param name="fileName"></param>
        public void Save(Image img, string fileName, int maxWidth, int maxHeight)
        {
            Bitmap bmp = new Bitmap(img);
            Size sz = InscribeImage(bmp.Width, bmp.Height, maxWidth, maxHeight);
            _newHeight = sz.Height;
            _newWidth = sz.Width;

            Bitmap thumb = new Bitmap(img, sz);

            FileInfo fi = new FileInfo(fileName);
            if (fi.Exists)
                fi.Delete();
            if (!fi.Directory.Exists)
                fi.Directory.Create();
            thumb.Save(fileName, img.RawFormat);
        }
    }
}
